﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls.WebParts;
using System.Xml;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebPartPages;

namespace EF
{
    public class EFSimpleReminder : SPJobDefinition
    {
        #region constant variables
        public const string JOB_NAME = "EFSimpleReminder";
        public const char JobName_SeparatorChar = ' ';

        public const string Configuration_ListTitle = @"EFSimpleReminderCfg";
        public const string Configuration_ListDescription = @"EFSimpleReminder configuration settings";
        //public const string Configuration_ListUrl = @"Lists/" + Configuration_ListTitle;
        public const string History_ListTitle = @"EFSimpleReminderHistory";
        public const string History_ListDescription = @"EFSimpleReminder History";
        //public const string History_ListUrl = @"Lists/" + History_ListTitle;
        public const string TaskDefault_ListTitle = @"Tasks";
        //public const string TaskDefault_ListUrl = @"Lists/" + TaskDefault_ListTitle;
        public const string Job_ListTitle = @"EFSimpleReminderJob";
        public const string Job_ListDescription = @"EF SharePoint 2010 SimpleReminder Job Links";
        //public const string Job_ListUrl = @"Lists/" + Job_ListTitle;

        //public const string Column_Title = @"Title";
        //public const string Column_LinkTitle = @"LinkTitle";

        //  SimpleReminderCfg
        public const string Column_EFSimpleReminderCfg_RecurringType = @"RecurringType";
        public const string Column_EFSimpleReminderCfg_WebUrl = @"WebUrl";
        public const string Column_EFSimpleReminderCfg_ViewUrl = @"ViewUrl";
        public const string Column_EFSimpleReminderCfg_ReminderSendTo = @"ReminderSendTo";   //also for SimpleReminderHistory list
        public const string Column_EFSimpleReminderCfg_ReminderSubject = @"ReminderSubject";
        public const string Column_EFSimpleReminderCfg_ReminderBody = @"ReminderBody";
        public const string Column_EFSimpleReminderCfg_AppendHtmlTag = @"AppendHtmlTag";
        public const string Column_EFSimpleReminderCfg_HtmlEncode = @"HtmlEncode";
        public const string Column_EFSimpleReminderCfg_ReminderCC = @"ReminderCC";   //also for SimpleReminderHistory list
        public const string Column_EFSimpleReminderCfg_NotificationType = @"NotificationType";   //also for SimpleReminderHistory list(single line of text)
        public const string Column_EFSimpleReminderCfg_TasksListTitle = @"TaskListTitle";
        public const string Column_EFSimpleReminderCfg_ReminderFrequency = @"ReminderFrequency";
        public const string Column_EFSimpleReminderCfg_LastScanTime = @"LastScanTime";
        public const string Column_EFSimpleReminderCfg_LastScanCount = @"LastScanCount";
        public const string Column_EFSimpleReminderCfg_IsActive = @"IsActive";

        //  SimpleReminderHistory
        public const string Column_EFSimpleReminderHistory_WebTitle = @"WebTitle";
        public const string Column_EFSimpleReminderHistory_ListTitle = @"ListTitle";
        public const string Column_EFSimpleReminderHistory_ItemId = @"ItemId";
        public const string Column_EFSimpleReminderHistory_ReminderSubject = @"Subject";
        public const string Column_EFSimpleReminderHistory_ReminderSendTo = @"SendTo";
        public const string Column_EFSimpleReminderHistory_ReminderCC = @"CC";
        public const string Column_EFSimpleReminderHistory_ItemUrl = @"ItemUrl";
        public const string Column_EFSimpleReminderHistory_TaskUrl = @"TaskUrl";

        //  SimpleReminderTask
        //public const string Column_EFSimpleReminderTask_ReminderSubject = @"ReminderSubject";
        //public const string Column_EFSimpleReminderTask_ReminderBody = @"ReminderBody";

        public const string ReminderFrequency_OneTimeOnly = @"One time only";
        public const string ReminderFrequency_Everytime = @"Everytime";

        public const string NotificationType_Email = @"Email";
        public const string NotificationType_Task = @"Task";

        //admin page
        public const string Column_EFSimpleReminderJob_AdminLink = @"AdminLink";

        public const string View_Portal = @"Portal";

        public const string RecurringType_Monthly = @"Monthly";
        public const string RecurringType_Weekly = @"Weekly";
        public const string RecurringType_Daily = @"Daily";
        public const string RecurringType_Hourly = @"Hourly";
        public const string RecurringType_Minutes = @"Minutes";

        public const string DocLib_SitePages_Title = @"Site Pages";
        public const string DocLib_SitePages_PathName = @"SitePages";
        public const string AdminPage_Name = @"EFSimpleReminderAdminLink";
        public const string AdminPage_Title = "EF SimpleReminder Admin Page";
        public const string AdminPage_Url = "SitePages/EFSimpleReminderAdminLink.aspx";

        public const string Zone_TitleBar = @"TitleBar";
        public const string Zone_Header = @"Header";
        public const string Zone_LeftColumn = @"LeftColumn";
        public const string Zone_MiddleColumn = @"MiddleColumn";
        public const string Zone_RightColumn = @"RightColumn";
        public const string Zone_Footer = @"Footer";

        public enum ListViewWebPartToolbarType
        {
            Standard = 0,       //Standard
            FreeForm = 1,       //Freeform
            None = 2,           //None
            ShowToolbar = 4     //ShowToolbar
        }
        #endregion

        public string _strReminderName = string.Empty;
        public string _strJobName = string.Empty;
        public bool _bAppendHtmlTag = false;
        public bool _bHtmlEncode = false;

        #region constructor
        public EFSimpleReminder()
            : base()
        {

        }

        public EFSimpleReminder(string strJobName, SPService service, SPServer server, SPJobLockType targetType)
            : base(strJobName, service, server, targetType)
        {

        }

        public EFSimpleReminder(string strJobName, SPWebApplication webApplication)
            : base(strJobName, webApplication, null, SPJobLockType.ContentDatabase)
        {
            this.Name = strJobName;
            this.Title = strJobName;
        }

        #endregion

        #region common functions
        public void logHistory(SPWeb objSPWeb, string strMessage)
        {
            logInfo(objSPWeb, strMessage, string.Empty, _strJobName);
        }

        public void logDebugInfo(SPWeb objSPWeb, string strMessage)
        {
#if DEBUG
            System.Reflection.Assembly objAssembly;
            objAssembly = this.GetType().Assembly;
            FileInfo objFileInfo = new FileInfo(objAssembly.Location);
            string strVersionInfo = string.Empty;
            strVersionInfo = string.Format(@"debug - {0} - {1}", objFileInfo.CreationTime, objAssembly.GetName().Version);
            logInfo(objSPWeb, strMessage, strVersionInfo, _strJobName);
#endif
        }

        public static void logInfo(SPWeb objSPWeb, string strMessage, string strVersionInfo, string strJobItemName)
        {
            if (string.IsNullOrEmpty(strMessage))
                return;

            string strLogMessage = strMessage;
            if (strLogMessage.Length > 230)
                strLogMessage = strLogMessage.Substring(0, 230);
            if (string.IsNullOrEmpty(strVersionInfo) == false)
            {
                strLogMessage = string.Format("{0} - {1}", strVersionInfo, strLogMessage);
            }

            SPList splistHistory = null;
            try
            {
                if (objSPWeb != null)
                {
                    using (SPSite objSPSite = new SPSite(objSPWeb.Site.ID))
                    {
                        using (SPWeb objSPWebRoot = objSPSite.RootWeb)
                        {
                            objSPWebRoot.AllowUnsafeUpdates = true;
                            splistHistory = objSPWebRoot.Lists.TryGetList(History_ListTitle);
                            if (splistHistory != null)
                            {
                                SPListItem itemHistory = splistHistory.AddItem();
                                itemHistory[SPBuiltInFieldId.Title] = strJobItemName;
                                itemHistory[Column_EFSimpleReminderHistory_WebTitle] = objSPWebRoot.Title;
                                itemHistory[Column_EFSimpleReminderHistory_ReminderSubject] = strLogMessage;
                                itemHistory.Update();
                            }
                            logTraceInfo(string.Format(@"{0} - {1} - {2}", strJobItemName, strVersionInfo, strMessage));
                            objSPWebRoot.AllowUnsafeUpdates = false;
                        }
                    }
                }
                else
                {
                    logTraceInfo(strMessage);
                }
            }
            catch (Exception ex)
            {
                logTraceInfo(string.Format(@"ex, strLogMessage={0}", strLogMessage));
                logTraceInfo(string.Format(@"ex.Message={0}", ex.Message));
                logTraceInfo(string.Format(@"ex.StackTrace={0}", ex.StackTrace));
                throw;
            }
        }

        public void logReminderHistory(string strReminderName, SPListItem itemTarget, string strSendTo, string strSubject, string strNotificationType, string strTasksListUrl)
        {
            logReminderHistory(this.GetType().Assembly, strReminderName, itemTarget, strSendTo, strSubject, strNotificationType, strTasksListUrl);
        }

        public static void logReminderHistory(System.Reflection.Assembly objAssembly, string strReminderName, SPListItem itemTarget, string strSendTo, string strSubject, string strNotificationType, string strTasksListUrl)
        {
            string strTitle = string.Empty;
            try
            {
                using (SPSite objSPSite = new SPSite(itemTarget.Web.Site.ID))
                {
                    using (SPWeb objSPWebRoot = objSPSite.RootWeb)
                    {
                        objSPWebRoot.AllowUnsafeUpdates = true;
                        SPList splistHistory = objSPWebRoot.Lists.TryGetList(History_ListTitle);
                        if (splistHistory == null)
                        {
                            logTraceInfo(string.Format(@"logReminderHistory(), cannot find {0} in web {1}", History_ListTitle, objSPWebRoot.Url));
                            return;
                        }

                        SPListItem itemHistory = splistHistory.AddItem();
                        //FileInfo objFileInfo = new FileInfo(objAssembly.Location);
                        //strTitle = string.Format(@"{0} - {1} - {2}", strJobName, objFileInfo.CreationTime, objAssembly.GetName().Version);
                        strTitle = string.Format(@"{0}", strReminderName);
                        itemHistory[SPBuiltInFieldId.Title] = strTitle;
                        itemHistory[Column_EFSimpleReminderHistory_WebTitle] = itemTarget.Web.Title;
                        itemHistory[Column_EFSimpleReminderHistory_ListTitle] = itemTarget.ParentList.Title;
                        itemHistory[Column_EFSimpleReminderHistory_ReminderSubject] = strSubject;
                        itemHistory[Column_EFSimpleReminderHistory_ItemId] = itemTarget.ID;
                        itemHistory[Column_EFSimpleReminderHistory_ReminderSendTo] = strSendTo;
                        itemHistory.Update();
                        objSPWebRoot.AllowUnsafeUpdates = false;
                    }
                }
            }
            catch (Exception ex)
            {
                logTraceInfo(string.Format(@"ex, strJobName={0}, itemTarget.Url={1}, strSendTo={2}, strSubject={3}, strNotificationType={4}, strTasksListUrl={5}", strReminderName, itemTarget.Url, strSendTo, strSubject, strNotificationType, strTasksListUrl));
                logTraceInfo(string.Format(@"ex.Message={0}", ex.Message));
                logTraceInfo(string.Format(@"ex.StackTrace={0}", ex.StackTrace));

                throw;
            }
        }

        public static string getFullJobName(string strUrl)
        {
            return getFullJobName(strUrl, string.Empty);
        }

        public static string getFullJobName(string strUrl, string strRecurringType)
        {
            string strReturn = strUrl;
            strReturn = strReturn.Substring(strReturn.IndexOf(@"//") + 2);
            strReturn = strReturn.Replace(@":", @"_");
            strReturn = strReturn.Replace(@"/", @"_");
            strReturn = string.Format(@"{0}{1}{2}", EFSimpleReminder.JOB_NAME, EFSimpleReminder.JobName_SeparatorChar, strReturn);

            if (string.IsNullOrEmpty(strRecurringType) == false)
            {
                strReturn += string.Format("{0}{1}", EFSimpleReminder.JobName_SeparatorChar, strRecurringType);
            }

            return strReturn;
        }

        public static void logTraceInfo(string strMessage)
        {
            if (string.IsNullOrEmpty(strMessage))
                return;

            SPDiagnosticsService diagSvc = SPDiagnosticsService.Local;
            diagSvc.WriteTrace(0,
                new SPDiagnosticsCategory(JOB_NAME, TraceSeverity.Monitorable, EventSeverity.Error),
                TraceSeverity.Monitorable,
                "{0}",
                new object[] { strMessage });
        }

        public static string getServerRelativeUrl(SPWeb objSPWeb, string strWebRelativeUrl)
        {
            string strServerRelativeUrl = string.Empty;
            string strWebServerRelativeUrl = objSPWeb.ServerRelativeUrl;
            if (strWebServerRelativeUrl == @"/") strWebServerRelativeUrl = string.Empty;

            strServerRelativeUrl = strWebServerRelativeUrl + strWebRelativeUrl;
            return strServerRelativeUrl;
        }

        public string replaceTags(SPListItem itemTarget, string strContent)
        {
            return replaceTags(itemTarget, strContent, false);
        }

        public string replaceTags(SPListItem itemTarget, string strContent, bool boolUserEmail)
        {
            string strReturn = strContent;
            string strTag = string.Empty;
            string strValue = string.Empty;
            int iCfgItemId = itemTarget.ID;

            using (SPWeb objSPWeb = itemTarget.Web)
            {
                foreach (SPField objSPField in itemTarget.Fields)
                {
                    try
                    {
                        strTag = string.Format("[{0}]", objSPField.Title);
                        if (strReturn.IndexOf(strTag, StringComparison.InvariantCultureIgnoreCase) < 0)
                            continue;

                        strValue = string.Empty;
                        if (objSPField.Type == SPFieldType.Lookup)
                        {
                            SPFieldLookupValue objLookupValue = (SPFieldLookupValue)itemTarget[objSPField.Title];
                            strValue = objLookupValue.LookupValue;
                        }
                        else if (objSPField.Type == SPFieldType.User)
                        {
                            SPFieldUserValue objUserValue = new SPFieldUserValue(objSPWeb, Convert.ToString(itemTarget[objSPField.InternalName]));
                            if (boolUserEmail)
                            {
                                strValue = objUserValue.User.Email;
                            }
                            else
                            {
                                strValue = objUserValue.User.Name;
                            }
                        }
                        else if (objSPField.Type == SPFieldType.URL)
                        {
                            SPFieldUrlValue objUrlValue = (SPFieldUrlValue)itemTarget[objSPField.Title];
                            strValue = string.Format(@"<a href='{0}'>{1}</a>", objUrlValue.Url, objUrlValue.Description);
                        }
                        else
                        {
                            strValue = Convert.ToString(itemTarget[objSPField.Title]);
                        }
                        strReturn = strReturn.Replace(strTag, strValue);
                    }
                    catch (Exception ex)
                    {
                        logTraceInfo(string.Format(@"ex, list title={0}, item id={1}, objSPField.Title={2}, strValue={3}, ItemId=", itemTarget.ParentList.Title, itemTarget.ID, objSPField.Title, strValue, iCfgItemId));
                        logTraceInfo(string.Format(@"ex.Message={0}", ex.Message));
                        logTraceInfo(string.Format(@"ex.StackTrace={0}", ex.StackTrace));

                        continue;
                    }
                }
            }

            return strReturn;
        }

        public static void AddWebPartConnection(
            SPWeb web,
            string pageUrl,
            string providerWebPartID,
            string consumerWebPartID,
            string providerConnectionPointName,
            string consumerConnectionPointName)
        {
            using (SPLimitedWebPartManager manager = web.GetLimitedWebPartManager(pageUrl, PersonalizationScope.Shared))
            {
                System.Web.UI.WebControls.WebParts.WebPart provider = manager.WebParts[providerWebPartID];
                System.Web.UI.WebControls.WebParts.WebPart consumer = manager.WebParts[consumerWebPartID];

                ProviderConnectionPointCollection providerPoints = manager.GetProviderConnectionPoints(provider);
                ConsumerConnectionPointCollection consumerPoints = manager.GetConsumerConnectionPoints(consumer);

                ProviderConnectionPoint providerPoint = null;

                foreach (ProviderConnectionPoint point in providerPoints)
                {
                    if (String.Equals(providerConnectionPointName, point.DisplayName, StringComparison.OrdinalIgnoreCase))
                    {
                        providerPoint = point;
                        break;
                    }
                }

                ConsumerConnectionPoint consumerPoint = null;

                foreach (ConsumerConnectionPoint point in consumerPoints)
                {
                    if (String.Equals(consumerConnectionPointName, point.DisplayName, StringComparison.OrdinalIgnoreCase))
                    {
                        consumerPoint = point;
                        break;
                    }
                }

                manager.SPConnectWebParts(provider, providerPoint, consumer, consumerPoint);
            }
        }

        public static void SetToolbarTypeFreeForm(SPWeb objSPWeb, string strPageUrl, Guid guidStorageKey)
        {
            string storageKey = guidStorageKey.ToString("B").ToUpper();
            uint toolbarType = (uint)EFSimpleReminder.ListViewWebPartToolbarType.FreeForm;

            if (String.IsNullOrEmpty(storageKey) || storageKey == Guid.Empty.ToString())
                throw new Exception("The webpart must be added to the page before this method (SetToolbarType) can be called");

            SPLimitedWebPartManager limitedWebPartManager = null;
            limitedWebPartManager = objSPWeb.GetLimitedWebPartManager(strPageUrl, PersonalizationScope.Shared);

            ListViewWebPart lvwp = null;
            lvwp = (ListViewWebPart)limitedWebPartManager.WebParts[guidStorageKey];

            string listId = lvwp.ListName;
            string viewId = lvwp.ViewGuid;

            // get the SPWebPartManager from SPLimitedWebPartManager
            PropertyInfo webPartManagerProp = typeof(SPLimitedWebPartManager).GetProperty(
              "WebPartManager",
              BindingFlags.NonPublic | BindingFlags.Instance);
            SPWebPartManager webPartManager = (SPWebPartManager)webPartManagerProp.GetValue(limitedWebPartManager, null);

            // get the SPWebPartConnection from SPWebPartManager
            PropertyInfo spWebPartsProp = typeof(SPWebPartManager).GetProperty(
              "SPWebParts",
              BindingFlags.NonPublic | BindingFlags.Instance);
            SPWebPartCollection webParts = (SPWebPartCollection)spWebPartsProp.GetValue(webPartManager, null);

            // Call the ApplyViewToListWebPart method on the SPWebPartConnection
            // internal void ApplyViewToListWebPart(
            //    string storageKey,
            //    string listID,
            //    string viewID,
            //    uint toolbarType,
            //    out uint flags,
            //    out uint baseViewId)
            MethodInfo applyViewToListWebPart = typeof(SPWebPartCollection).GetMethod(
              "ApplyViewToListWebPart",
              BindingFlags.NonPublic | BindingFlags.Instance,
              null,
              new[]{
        typeof(string),
        typeof(string),
        typeof(string),
        typeof(uint),
        typeof(uint).MakeByRefType(),
        typeof(uint).MakeByRefType()
      },
              null);
            object[] parameters = new object[6];
            parameters[0] = storageKey;
            parameters[1] = listId;
            parameters[2] = viewId;
            parameters[3] = toolbarType;

            applyViewToListWebPart.Invoke(webParts, parameters);
        }

        public static void ShowToolbar(SPWeb objSPWeb, string strPageUrl, Guid guidStorageKey)
        {
            SPLimitedWebPartManager manager = null;
            manager = objSPWeb.GetLimitedWebPartManager(strPageUrl, PersonalizationScope.Shared);

            object[] setToolbarTypeParams = { (uint)EFSimpleReminder.ListViewWebPartToolbarType.ShowToolbar };
            ListViewWebPart objListViewWebPart = null;
            objListViewWebPart = (ListViewWebPart)manager.WebParts[guidStorageKey];

            PropertyInfo viewProp = objListViewWebPart.GetType().GetProperty("View", BindingFlags.Instance | BindingFlags.NonPublic);
            SPView webPartView = viewProp.GetValue(objListViewWebPart, null) as SPView;

            MethodInfo setToolbarType = webPartView.GetType().GetMethod("SetToolbarType",
                BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(uint) }, null);
            setToolbarType.Invoke(webPartView, setToolbarTypeParams);

            webPartView.Update();
            manager.SaveChanges(objListViewWebPart);
        }

        public static string FormattingForTaskBody(string strBody)
        {
            string strReturn = string.Empty;

            strReturn = strBody.Trim();
            if (strReturn.IndexOf(Environment.NewLine) > 0)
            {
                strReturn = strReturn.Replace(Environment.NewLine, @"</div><div>");
                strReturn = @"<div>" + strReturn + @"</div>";
            }

            return strReturn;
        }

        #endregion

        public void processOneSPListItemEmail(SPWeb objSPWeb, SPListItem itemTarget, string strReminderSendTo, string strReminderCC, string strReminderSubject, string strReminderBody)
        {
            string strReminderSendToCurrent = string.Empty;
            string strReminderCCCurrent = string.Empty;
            string strReminderSubjectCurrent = string.Empty;
            string strReminderBodyCurrent = string.Empty;

            try
            {
                strReminderSendToCurrent = replaceTags(itemTarget, strReminderSendTo, true);
                strReminderCCCurrent = replaceTags(itemTarget, strReminderCC, true);
                logDebugInfo(objSPWeb, string.Format(@"processOneSPListItemEmail(), strReminderSendTo={0}, strReminderSendToCurrent={1}", strReminderSendTo, strReminderSendToCurrent));
                strReminderSubjectCurrent = replaceTags(itemTarget, strReminderSubject);
                strReminderBodyCurrent = replaceTags(itemTarget, strReminderBody);

                SPUtility.SendEmail(objSPWeb, _bAppendHtmlTag, _bHtmlEncode, strReminderSendToCurrent, strReminderSubjectCurrent, strReminderBodyCurrent);

                //log history
                logReminderHistory(_strReminderName, itemTarget, strReminderSendToCurrent, strReminderSubjectCurrent, NotificationType_Email, string.Empty);
            }
            catch (Exception ex)
            {
                logTraceInfo(string.Format(@"processOneSPListItemEmail(), ex, list title={0}, item id={1}", itemTarget.ParentList.Title, itemTarget.ID));
                logTraceInfo(string.Format(@"processOneSPListItemEmail(), ex.Message={0}", ex.Message));
                logTraceInfo(string.Format(@"processOneSPListItemEmail(), ex.StackTrace={0}", ex.StackTrace));

                throw;
            }
        }

        public void processOneSPListItemTask(SPWeb objSPWeb, SPListItem itemTarget, string strReminderSendTo, string strReminderSubject, string strReminderBody, string strTasksListTitle)
        {
            string strMessage = string.Empty;
            string strReminderSendToCurrent = string.Empty;
            string strReminderSubjectCurrent = string.Empty;
            string strReminderBodyCurrent = string.Empty;

            try
            {
                strReminderSendToCurrent = replaceTags(itemTarget, strReminderSendTo, true);
                //logInfo(objSPWeb, string.Format(@"processOneSPListItemTask(), strReminderSendTo={0}, strReminderSendToCurrent={1}", strReminderSendTo, strReminderSendToCurrent));
                strReminderSubjectCurrent = replaceTags(itemTarget, strReminderSubject);
                strReminderBodyCurrent = replaceTags(itemTarget, strReminderBody);

                SPList splistTasks = null;
                splistTasks = objSPWeb.Lists.TryGetList(strTasksListTitle);
                if (splistTasks == null)
                {
                    strMessage = string.Format(@"processOneSPListItemTask(), cannot find {0} in web {1}", strTasksListTitle, objSPWeb.Url);
                    logHistory(objSPWeb.Site.RootWeb, strMessage);
                    logTraceInfo(strMessage);
                    return;
                }

                //create new tasks
                string[] separator = new string[] { @";" };

                string[] strSplitArr = strReminderSendToCurrent.Split(separator, StringSplitOptions.RemoveEmptyEntries);
                SPUser objSPUser = null;
                foreach (string arrStrEmailTo in strSplitArr)
                {
                    if (string.IsNullOrEmpty(arrStrEmailTo))
                        continue;
                    if (arrStrEmailTo.IndexOf('[') >= 0 || arrStrEmailTo.IndexOf(']') >= 0)
                        continue;

                    try
                    {
                        objSPUser = null;
                        if (arrStrEmailTo.IndexOf('@') >= 0)
                        {
                            objSPUser = objSPWeb.AllUsers.GetByEmail(arrStrEmailTo.Trim());
                        }
                        else if (arrStrEmailTo.IndexOf('\\') >= 0)
                        {
                            objSPUser = objSPWeb.AllUsers[arrStrEmailTo.Trim()];
                        }
                        else
                        {
                            continue;
                        }
                        if (objSPUser == null)
                            continue;

                        SPListItem objSPListItem = splistTasks.AddItem();
                        //objSPListItem[SPBuiltInFieldId.Title] = _strJobItemName;
                        objSPListItem[SPBuiltInFieldId.Title] = strReminderSubjectCurrent;
                        objSPListItem[SPBuiltInFieldId.AssignedTo] = objSPUser;
                        strReminderBodyCurrent = FormattingForTaskBody(strReminderBodyCurrent);
                        objSPListItem[SPBuiltInFieldId.Body] = strReminderBodyCurrent;
                        objSPListItem.Update();

                        logReminderHistory(_strReminderName, itemTarget, objSPUser.LoginName, strReminderSubjectCurrent, NotificationType_Task, TaskDefault_ListTitle);
                    }
                    catch (Exception ex)
                    {
                        logTraceInfo(string.Format(@"processOneSPListItemTask(), User account doesn't exist(Email={0})", arrStrEmailTo));
                        //logTraceInfo(string.Format(@"processOneSPListItemTask(), strReminderSubjectCurrent={0}", strReminderSubjectCurrent));
                        logTraceInfo(string.Format(@"processOneSPListItemTask(), ex.Message={0}", ex.Message));
                        logTraceInfo(string.Format(@"processOneSPListItemTask(), ex.StackTrace={0}", ex.StackTrace));

                        continue;
                    }
                }
            }
            catch (Exception ex)
            {
                logTraceInfo(string.Format(@"processOneSPListItemTask(), ex, list title={0}, item id={1}", itemTarget.ParentList.Title, itemTarget.ID));
                logTraceInfo(string.Format(@"processOneSPListItemTask(), ex.Message={0}", ex.Message));
                logTraceInfo(string.Format(@"processOneSPListItemTask(), ex.StackTrace={0}", ex.StackTrace));

                throw;
            }
        }

        public void markOneSPListItem(SPWeb objSPWebRoot, SPListItem itemTarget, int iItemCount)
        {
            itemTarget[Column_EFSimpleReminderCfg_LastScanTime] = DateTime.Now;
            itemTarget[Column_EFSimpleReminderCfg_LastScanCount] = iItemCount;
            itemTarget.SystemUpdate(false);
        }

        public void processOneJobitem(SPWeb objSPWebRoot, SPListItem objReminderItem)
        {
            SPView spviewTarget = null;
            SPList splistTarget = null;
            SPListItemCollection itemCollectionTarget = null;
            SPListItem objCurrentSPListItem = null;

            string strViewUrl = string.Empty;
            string strWebUrl = string.Empty;
            string strReminderSendTo = string.Empty;
            string strReminderSubject = string.Empty;
            string strReminderBody = string.Empty;
            string strReminderCC = string.Empty;
            string strNotificationType = string.Empty;
            string strReminderFrequency = string.Empty;
            string strTasksListUrl = string.Empty;
            //string strLastScanTime = string.Empty;

            try
            {
                _strReminderName = Convert.ToString(objReminderItem[SPBuiltInFieldId.Title]);

                SPFieldChoice choiceFieldReminderFrequency = objReminderItem.Fields.GetFieldByInternalName(Column_EFSimpleReminderCfg_ReminderFrequency) as SPFieldChoice;
                strReminderFrequency = choiceFieldReminderFrequency.GetFieldValueAsText(objReminderItem[choiceFieldReminderFrequency.Title]);
                //strLastScanTime = Convert.ToString(objReminderItem[Column_EFSimpleReminderCfg_LastScanTime]);
                strWebUrl = Convert.ToString(objReminderItem[Column_EFSimpleReminderCfg_WebUrl]);
                strViewUrl = Convert.ToString(objReminderItem[Column_EFSimpleReminderCfg_ViewUrl]);
                strReminderSendTo = Convert.ToString(objReminderItem[Column_EFSimpleReminderCfg_ReminderSendTo]);
                strReminderCC = Convert.ToString(objReminderItem[Column_EFSimpleReminderCfg_ReminderCC]);
                SPFieldMultiChoiceValue objNotificationType = new SPFieldMultiChoiceValue(objReminderItem[Column_EFSimpleReminderCfg_NotificationType].ToString());
                strTasksListUrl = Convert.ToString(objReminderItem[Column_EFSimpleReminderCfg_TasksListTitle]);
                strReminderSubject = Convert.ToString(objReminderItem[Column_EFSimpleReminderCfg_ReminderSubject]);
                strReminderBody = Convert.ToString(objReminderItem[Column_EFSimpleReminderCfg_ReminderBody]);
                SPFieldBoolean boolField = objReminderItem.Fields[Column_EFSimpleReminderCfg_AppendHtmlTag] as SPFieldBoolean;
                _bAppendHtmlTag = (bool)boolField.GetFieldValue(Convert.ToString(objReminderItem[Column_EFSimpleReminderCfg_AppendHtmlTag]));
                boolField = objReminderItem.Fields[Column_EFSimpleReminderCfg_HtmlEncode] as SPFieldBoolean;
                _bHtmlEncode = (bool)boolField.GetFieldValue(Convert.ToString(objReminderItem[Column_EFSimpleReminderCfg_HtmlEncode]));

                using (SPSite site = new SPSite(objSPWebRoot.Site.ID))
                {
                    if (strWebUrl == @"/")
                        strWebUrl = string.Empty;

                    using (SPWeb objSPWeb = site.OpenWeb(strWebUrl))
                    {
                        if (objSPWeb.Exists == false)
                        {
                            logInfo(objSPWebRoot, string.Format(@"Sub site {0} doesn't exist!", strWebUrl), string.Empty, _strReminderName);
                            return;
                        }

                        spviewTarget = objSPWeb.GetViewFromUrl(strViewUrl);
                        if (spviewTarget == null)
                        {
                            logInfo(objSPWebRoot, string.Format(@"List view {0} doesn't exist in web {1}.", strViewUrl, strWebUrl), string.Empty, _strReminderName);
                        }

                        splistTarget = spviewTarget.ParentList;
                        itemCollectionTarget = splistTarget.GetItems(spviewTarget);

                        foreach (SPListItem itemTarget in itemCollectionTarget)
                        {
                            try
                            {
                                objCurrentSPListItem = splistTarget.GetItemById(itemTarget.ID);
                                if (strReminderFrequency == ReminderFrequency_OneTimeOnly)
                                {
                                    // to check the history that whether this item was excuted before
                                }

                                for (int i = 0; i < objNotificationType.Count; i++)
                                {
                                    try
                                    {
                                        strNotificationType = objNotificationType[i];
                                        if (strNotificationType.Equals(NotificationType_Email, StringComparison.InvariantCultureIgnoreCase))
                                        {
                                            processOneSPListItemEmail(objSPWeb, objCurrentSPListItem, strReminderSendTo, strReminderCC, strReminderSubject, strReminderBody);
                                        }
                                        else if (strNotificationType.Equals(NotificationType_Task, StringComparison.InvariantCultureIgnoreCase))
                                        {
                                            processOneSPListItemTask(objSPWeb, objCurrentSPListItem, strReminderSendTo, strReminderSubject, strReminderBody, strTasksListUrl);
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        logTraceInfo(string.Format(@"processOneJobitem(), strNotificationType={0}, objCurrentSPListItem.Url={1}, objSPWeb.ServerRelativeUrl={2}", strNotificationType, objCurrentSPListItem.Url, objSPWeb.ServerRelativeUrl));
                                        logTraceInfo(string.Format(@"processOneJobitem(), ex.Message={0}", ex.Message));
                                        logTraceInfo(string.Format(@"processOneJobitem(), ex.StackTrace={0}", ex.StackTrace));

                                        continue;
                                    }
                                }
                            }
                            catch
                            {
                                continue;
                            }
                        }

                        markOneSPListItem(objSPWebRoot, objReminderItem, itemCollectionTarget.Count);
                    }   // end of "using (SPWeb)"
                }   // end of "using (SPSite)"
            }
            catch (Exception ex)
            {
                logTraceInfo(string.Format(@"processOneJobitem(), ex, strTasksListUrl={0}, strNotificationType={1}", strTasksListUrl, strNotificationType));
                logTraceInfo(string.Format(@"processOneJobitem(), ex.Message={0}", ex.Message));
                logTraceInfo(string.Format(@"processOneJobitem(), ex.StackTrace={0}", ex.StackTrace));

                throw;
            }
        }

        public void processOneSiteCollection(SPSite objSPSite, string strRecurringType)
        {
            //string strReminderFrequency = string.Empty;
            //bool bEmailSent = false;

            SPList splistJob = null;
            SPList splistHistory = null;
            SPList splistTask = null;
            SPView objSPView = null;
            SPListItem objCurrentJobItem = null;
            SPListItemCollection objSPListItemCollection = null;

            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPWeb objSPWebRoot = objSPSite.OpenWeb(objSPSite.RootWeb.ID))
                {
                    try
                    {
                        splistHistory = objSPWebRoot.Lists.TryGetList(History_ListTitle);
                        if (splistHistory == null)
                        {
                            logTraceInfo(string.Format(@"EFSimpleReminder - cannot find history list {0} in web {1}", History_ListTitle, objSPWebRoot.Url));
                            return;
                        }

                        _strJobName = this.Title;

                        splistJob = objSPWebRoot.Lists.TryGetList(Configuration_ListTitle);
                        if (splistJob == null)
                        {
                            logHistory(objSPWebRoot, string.Format(@"cannot find configuration list {0} in web {1}", Configuration_ListTitle, objSPWebRoot.Url));
                            return;
                        }

                        splistTask = objSPWebRoot.Lists.TryGetList(TaskDefault_ListTitle);
                        if (splistJob == null)
                        {
                            logHistory(objSPWebRoot, string.Format(@"cannot find task list {0} in web {1}", TaskDefault_ListTitle, objSPWebRoot.Url));
                            return;
                        }

                        objSPView = splistJob.Views[strRecurringType];
                        objSPListItemCollection = splistJob.GetItems(objSPView);
                        logDebugInfo(objSPWebRoot, string.Format(@"objSPListItemCollection.Count={0}, objSPView.Url={1}, objSPView.Query={2}", objSPListItemCollection.Count, objSPView.Url, objSPView.Query));
                        if (objSPListItemCollection.Count > 0)
                            logTraceInfo(string.Format(@"Job ({0}) begin......", _strJobName));

                        foreach (SPListItem objJobitem in objSPListItemCollection)
                        {
                            try
                            {
                                objCurrentJobItem = splistJob.GetItemById(objJobitem.ID);
                                processOneJobitem(objSPWebRoot, objCurrentJobItem);
                            }
                            catch
                            {
                                continue;
                            }

                            //objJobitem[Column_EFSimpleReminderCfg_EmailSent] = true;
                            //objJobitem.Update();
                        }

                        if (objSPListItemCollection.Count > 0)
                            logTraceInfo(string.Format(@"Job ({0}) completed.", _strJobName));
                    }
                    catch (Exception ex)
                    {
                        logHistory(objSPWebRoot, string.Format(@"objSPListItemCollection.Count={0}, objSPView.Url={1}, objSPView.Query={2}", objSPListItemCollection.Count, objSPView.Url, objSPView.Query));
                        logHistory(objSPWebRoot, string.Format(@"ex, Configuration_ListTitle={0}, objSPSite.ServerRelativeUrl={1}", getServerRelativeUrl(objSPWebRoot, Configuration_ListTitle), objSPSite.ServerRelativeUrl));
                        logHistory(objSPWebRoot, string.Format(@"ex.Message={0}", ex.Message));
                        logHistory(objSPWebRoot, string.Format(@"ex.StackTrace={0}", ex.StackTrace));
                        logTraceInfo(string.Format(@"ex.Message={0}", ex.Message));
                        logTraceInfo(string.Format(@"ex.StackTrace={0}", ex.StackTrace));

                        throw;
                    }
                }
            });
        }

        public override void Execute(Guid contentDbId)
        {
            SPWebApplication webApplication = this.Parent as SPWebApplication;
            SPContentDatabase contentDb = webApplication.ContentDatabases[contentDbId];
            string strSiteName = string.Empty;
            string strRecurringType = string.Empty;

            strRecurringType = this.Title.Substring(this.Title.LastIndexOf(JobName_SeparatorChar) + 1);

            // get a reference to the "ListTimerJob" list in the RootWeb of the first site collection in the content database
            foreach (SPSite objSPSite in contentDb.Sites)
            {
                try
                {
                    strSiteName = getFullJobName(objSPSite.Url);
                    if (this.Title.StartsWith(strSiteName, StringComparison.InvariantCultureIgnoreCase) == false)
                        continue;

                    processOneSiteCollection(objSPSite, strRecurringType);
                }
                catch (Exception ex)
                {
                    logTraceInfo(string.Format(@"ex, strRecurringType={0}, strSiteName={1}, objSPSite.Url={2}",
                        strRecurringType, strSiteName, objSPSite.Url));
                    logTraceInfo(string.Format(@"ex.Message={0}", ex.Message));
                    logTraceInfo(string.Format(@"ex.StackTrace={0}", ex.StackTrace));

                    continue;
                }
                finally
                {
                    objSPSite.Dispose();
                }
            }

            //SPListItem newList = Listjob.Items.Add();
            //newList["Title"] = DateTime.Now.ToString();
            //newList.Update();
        }
    }
}
